package com.xq.shop.util;

import java.sql.SQLException;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;

import com.xq.shop.vo.SearchObject;
import com.xq.shop.vo.SearchValue;
import com.xq.shop.vo.SearchValue.Pattern;

@SuppressWarnings("unchecked")
public class HibernateUtil {

	private static SessionFactory sessionFactory;
	private static HibernateTemplate hibernateTemplate;
	
	public static HibernateTemplate getTemplate() {
		return HibernateUtil.hibernateTemplate;
	}
	
	public static SessionFactory getSessionFactory() {
		return sessionFactory;
	}
	public void setSessionFactory(SessionFactory sessionFactory) {
		HibernateUtil.sessionFactory = sessionFactory;
		HibernateUtil.hibernateTemplate = new HibernateTemplate(sessionFactory);
	}
	
	public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
		HibernateUtil.hibernateTemplate = hibernateTemplate;
	}
	
	/**
	 * 不带参数的数量查询
	 * @param clazz
	 * @return
	 */
//	public static int getCount(Class clazz){
//		
//		DetachedCriteria criteria = DetachedCriteria.forClass(clazz);
//		criteria.setProjection(Projections.rowCount());
//		List list = hibernateTemplate.findByCriteria(criteria);
//		return list.size() > 0 ? ((Long)list.get(0)).intValue() : 0;
//	}
	
	/**
	 * 带有查询条件的数量查询
	 * @param clazz
	 * @param param
	 * @return
	 */
	public static int getCount(Class clazz, SearchObject search){
		
		DetachedCriteria criteria = DetachedCriteria.forClass(clazz);
		
		for(SearchValue condition : search.getCondition()){
			
			if(condition.isBlank()) continue;
			
			if(Pattern.LIKE.equals(condition.getPattern())){
				
				criteria.add(Restrictions.like(condition.getName(), "%" + condition.getValue() + "%"));
				
			} else if(Pattern.IN.equals(condition.getPattern())){
				
				if(condition.getValue() instanceof Collection){
					criteria.add(Restrictions.in(condition.getName(), (Collection)condition.getValue()));
				} else {
					criteria.add(Restrictions.in(condition.getName(), (Object[]) condition.getValue()));
				}
				
			} else if(Pattern.EQUAL.equals(condition.getPattern())){
				
				criteria.add(Restrictions.eq(condition.getName(), condition.getValue()));
			}
		}
		
		criteria.setProjection(Projections.rowCount());
		List list = hibernateTemplate.findByCriteria(criteria);
		return list.size() > 0 ? ((Long)list.get(0)).intValue() : 0;
	}
	
	/**
	 * 只有排序的查询
	 * @param clazz		查询的对象
	 * @param order		排序map
	 * @param pageNum	页码
	 * @param pageSize	行数
	 * @return
	 */
	public static List getPageObject(Class clazz, SearchObject search){
		
		DetachedCriteria criteria = DetachedCriteria.forClass(clazz);
		
		for(SearchValue condition : search.getCondition()){
			
			if(condition.isBlank()) continue;
			
			if(Pattern.LIKE.equals(condition.getPattern())){
				
				criteria.add(Restrictions.like(condition.getName(), "%" + condition.getValue() + "%"));
				
			} else if(Pattern.IN.equals(condition.getPattern())){
				
				if(condition.getValue() instanceof Collection){
					criteria.add(Restrictions.in(condition.getName(), (Collection)condition.getValue()));
				} else {
					criteria.add(Restrictions.in(condition.getName(), (Object[]) condition.getValue()));
				}
				
			} else if(Pattern.EQUAL.equals(condition.getPattern())){
				
				criteria.add(Restrictions.eq(condition.getName(), condition.getValue()));
			}
		}
		
		Map<String, SearchValue.Order> order = search.getOrder();
		Iterator<String> iterator = order.keySet().iterator();
		String key;
		while(iterator.hasNext()){
			
			key = iterator.next();
			
			if(SearchValue.Order.ASC.equals(order.get(key))){
				criteria.addOrder(Order.asc(key));
			} else if(SearchValue.Order.DESC.equals(order.get(key))) {
				criteria.addOrder(Order.desc(key));
			}
		}
		
		return hibernateTemplate.findByCriteria(criteria, (search.getPageNum()-1)*search.getPageSize(), search.getPageSize());
	}
	
	public static Object execute(final String sql, final Map<String, Object> param){
		
		return hibernateTemplate.execute(new HibernateCallback() {
			
			@Override
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				
				Query query = session.createQuery(sql);
				
				Iterator<String> iterator = param.keySet().iterator();
				while(iterator.hasNext()){
					
					String key = iterator.next();
					Object value = param.get(key);
					if(value instanceof Collection){
						query.setParameterList(key, (Collection)value);
					} else if(value instanceof Object[]) {
						query.setParameterList(key, (Object[])value);
					} else {
						query.setParameter(key, value);
					}
				}
				
				return query.executeUpdate();
			}
		});
	}
	
	public static Object executeFind(final String sql, final Map<String, Object> param){
		
		return hibernateTemplate.execute(new HibernateCallback() {
			
			@Override
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				
				Query query = session.createQuery(sql);
				
				Iterator<String> iterator = param.keySet().iterator();
				while(iterator.hasNext()){
					
					String key = iterator.next();
					Object value = param.get(key);
					if(value instanceof Collection){
						query.setParameterList(key, (Collection)value);
					} else if(value instanceof Object[]) {
						query.setParameterList(key, (Object[])value);
					} else {
						query.setParameter(key, value);
					}
				}
				List result = query.list();
				session.clear();
				session.close();
				return result;
			}
		});
	}
}
